import * as PIXI from 'pixi.js'
import GetResource from './getResource'
import { nameSeries, nameCategory, nameElement, nameType, nameSkillConsume, rankNames, isOfficialCategory } from '@renderer/config'
import { categoryText } from '../textFactory'

// 卡册
PIXI.Assets.addBundle('cardBook', await GetResource.initAssets())
// 图标
PIXI.Assets.addBundle('icons', await GetResource.iconAssets())
// 按钮
PIXI.Assets.addBundle('module', await GetResource.moduleAssets())
// 卡牌
PIXI.Assets.addBundle('cardModule', await GetResource.cardModuleAssets())
// 载入卡牌资源
await GetResource.cardsAssets()
// 载入DIY卡牌资源
await GetResource.diyCardsAssets()

// 卡牌模块数据
const moduleData: Record<string, Wx.Sprite.Data | null> = {
  category: null,
  element: null,
  series: null,
  type: null,
  skillConsume: null,
  btns: null,
  sprite: null,
}
const modulePromise: Record<string, Promise<{ frames: Wx.Sprite.Data }> | null> = {
  category: null,
  element: null,
  series: null,
  type: null,
  skillConsume: null,
  btns: null,
  sprite: null,
}
const getModuleData = async (name: string): Promise<Wx.Sprite.Data> => {
  if (moduleData[name] === null) {
    if (modulePromise[name] === null) {
      modulePromise[name] = GetResource.spriteJson<{ frames: Wx.Sprite.Data }>(`/assets/sprite/${name}.json`)
    }
    // 载入数据
    const { frames } = await modulePromise[name]
    Object.entries(frames).forEach(([, value]) => {
      const { x, y, w, h } = value.frame
      value._frame = [x, y, w, h]
    })
    moduleData[name] = frames
  }
  return moduleData[name]
}
/** 卡牌类型*/
export const typeModule = async (cardData: Wx.Card.Param): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame } = (await getModuleData('type'))[nameType(cardData)]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.type,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}
/** 卡牌系列和品阶*/
export const seriesModule = async (cardData: Wx.Card.Param): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame } = (await getModuleData('series'))[nameSeries(cardData)]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.series,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}
/** 卡牌类别 */
export const categoryModule = async (cardData: Wx.Card.Param): Promise<PIXI.Sprite | PIXI.Text> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  if (isOfficialCategory(cardData)) {
    const moduleData = (await getModuleData('category'))[nameCategory(cardData)]
    return new PIXI.Sprite(
      new PIXI.Texture({
        source: bundle.category,
        frame: new PIXI.Rectangle(...moduleData._frame!),
      }),
    )
  } else {
    return categoryText(cardData.category || '')
  }
}
/** 卡牌五行*/
export const elementModule = async (cardData: Wx.Card.Param, index: number): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame } = (await getModuleData('element'))[nameElement(cardData, index)]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.element,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}
/** 卡牌技能消耗*/
export const skillConsumeModule = async (cardData: Wx.Card.Param): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame } = (await getModuleData('skillConsume'))[nameSkillConsume(cardData)]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.skillConsume,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}
/** 按钮精灵*/
export const btnsModule = async (name: string): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('module')
  const { _frame } = (await getModuleData('btns'))[name]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.btns,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}

export const rankSprites = async (): Promise<PIXI.Sprite[]> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const names = rankNames()
  return await Promise.all(
    Object.values(names).map(async (name) => {
      const { _frame } = (await getModuleData('sprite'))[name]
      return new PIXI.Sprite(
        new PIXI.Texture({
          source: bundle.sprite,
          frame: new PIXI.Rectangle(..._frame!),
        }),
      )
    }),
  )
}

export const createSprite = async (name: string): Promise<PIXI.Sprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame } = (await getModuleData('sprite'))[name]
  return new PIXI.Sprite(
    new PIXI.Texture({
      source: bundle.sprite,
      frame: new PIXI.Rectangle(..._frame!),
    }),
  )
}

export const createNsSprite = async (name: string, width?: number, height?: number): Promise<PIXI.NineSliceSprite> => {
  const bundle = await PIXI.Assets.loadBundle('cardModule')
  const { _frame, borders } = (await getModuleData('sprite'))[name]
  return new PIXI.NineSliceSprite({
    texture: new PIXI.Texture({
      source: bundle.sprite,
      frame: new PIXI.Rectangle(..._frame!),
    }),
    leftWidth: borders.left,
    rightWidth: borders.right,
    topHeight: borders.top,
    bottomHeight: borders.bottom,
    width,
    height,
  })
}

/** 生成卡牌能力文本 */
export const abilityText = async (data: Wx.Card.Data, container: PIXI.Container<PIXI.ContainerChild>): Promise<void> => {
  container.removeChildren()
  // 创建文本对象
  const text = new PIXI.Text({
    text: data.ability,
    alpha: 0.9,
    style: {
      fontFamily: 'XQFont',
      fontSize: data.transform.abilityFontSize,
      fill: 0xffffff,
      align: 'center',
      lineHeight: data.transform.abilityFontSize,
    },
  })
  text.anchor.set(0.5)
  container.addChild(text)
  // 文本有多少行
  const rowNum = data.ability.split('').filter((char) => char === '\n').length
  const pattern = /\{\{TP(\d+|\?)\}\}/
  const match = data.ability.match(pattern) as Array<string>
  if (match) {
    let skillConsume = match[1] as Wx.Card.SKILL_CONSUME
    if (skillConsume === '?' || Number(skillConsume) > 8) {
      skillConsume = '?'
    }
    const point = { x: 0, y: 0 }
    const newText = data.ability.replace(match[0], (_r, i) => {
      // 图标之前后多少个换行符, 即图标所在行的下标
      const beforeRowNum = data.ability
        .substring(0, i)
        .split('')
        .filter((char) => char === '\n').length
      // 所在行的内容
      const rowStr = data.ability.split('\n')[beforeRowNum]
      // 所在行的图标之后的内容
      const afterRowStr = data.ability.substring(i).split('\n')[0]
      // 计算文本宽度
      const tempText = new PIXI.Text({
        text: rowStr,
        style: { fontSize: data.transform.abilityFontSize },
      })
      const temp2Text = new PIXI.Text({
        text: afterRowStr,
        style: { fontSize: data.transform.abilityFontSize },
      })
      const place = '     '
      const temp3Text = new PIXI.Text({
        text: place,
        style: { fontSize: data.transform.abilityFontSize },
      })
      point.x = tempText.width / 2 - temp2Text.width + temp3Text.width
      point.y = beforeRowNum - rowNum / 2
      return place
    })
    const sprite = await skillConsumeModule({ skillConsume })
    sprite.anchor.set(0.5)
    sprite.scale.set((data.transform.abilityFontSize / 28) * 0.64)
    sprite.position.set(point.x, point.y * sprite.height)
    text.text = newText
    container.addChild(sprite) // 文字的中轴在文字区域的中间部分
  }
}

export * from './setWindow' // 设置窗口
export * from './accessories' // 装饰
